﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;


namespace botliga
{
    public class CBNCSUtilInterface
    {
        BNSharp.MBNCSUtil.NLS m_NLS;
        List<Byte> m_EXEVersion;			// set in HELP_SID_AUTH_CHECK
        List<Byte> m_EXEVersionHash;		// set in HELP_SID_AUTH_CHECK
        string m_EXEInfo;				// set in HELP_SID_AUTH_CHECK
        List<Byte> m_KeyInfoROC;			// set in HELP_SID_AUTH_CHECK
        List<Byte> m_KeyInfoTFT;			// set in HELP_SID_AUTH_CHECK
        List<Byte> m_ClientKey;			// set in HELP_SID_AUTH_ACCOUNTLOGON
        List<Byte> m_M1;					// set in HELP_SID_AUTH_ACCOUNTLOGONPROOF
        List<Byte> m_PvPGNPasswordHash;	// set in HELP_PvPGNPasswordHash
        string UserName;
        public CBNCSUtilInterface(string userName, string userPassword)
        {
            UserName = userName;
            m_NLS = new BNSharp.MBNCSUtil.NLS(userName, userPassword);
        }

        public List<Byte> GetEXEVersion() { return m_EXEVersion; }
        public List<Byte> GetEXEVersionHash() { return m_EXEVersionHash; }
        public string GetEXEInfo() { return m_EXEInfo; }
        public List<Byte> GetKeyInfoROC() { return m_KeyInfoROC; }
        public List<Byte> GetKeyInfoTFT() { return m_KeyInfoTFT; }
        public List<Byte> GetClientKey() { return m_ClientKey; }
        public List<Byte> GetM1() { return m_M1; }
        public List<Byte> GetPvPGNPasswordHash() { return m_PvPGNPasswordHash; }

        public void SetEXEVersion(List<Byte> nEXEVersion) { m_EXEVersion = nEXEVersion; }
        public void SetEXEVersionHash(List<Byte> nEXEVersionHash) { m_EXEVersionHash = nEXEVersionHash; }

        public void Reset(string userName, string userPassword)
        {
            m_NLS = new BNSharp.MBNCSUtil.NLS(userName, userPassword);
        }

        public bool HELP_SID_AUTH_CHECK(bool TFT, string war3Path, string keyROC, string keyTFT, string valueStringFormula, string mpqFileName, List<Byte> clientToken, List<Byte> serverToken)
        {
            // set m_EXEVersion, m_EXEVersionHash, m_EXEInfo, m_InfoROC, m_InfoTFT

            string FileWar3EXE = war3Path + "war3.exe";
            string FileStormDLL = war3Path + "Storm.dll";

            if (!File.Exists(FileStormDLL))
                FileStormDLL = war3Path + "storm.dll";

            string FileGameDLL = war3Path + "game.dll";
            bool ExistsWar3EXE = File.Exists(FileWar3EXE);
            bool ExistsStormDLL = File.Exists(FileStormDLL);
            bool ExistsGameDLL = File.Exists(FileGameDLL);

            if (ExistsWar3EXE && ExistsStormDLL && ExistsGameDLL)
            {
                // todotodo: check getExeInfo return value to ensure 1024 bytes was enough

                UInt32 EXEVersion;
                EXEVersion = (uint)BNSharp.MBNCSUtil.CheckRevision.GetExeInfo(FileWar3EXE, out m_EXEInfo);

                m_EXEVersion = Util.UTIL_CreateByteArray(EXEVersion, false);
                UInt32 EXEVersionHash;
                EXEVersionHash = (uint)BNSharp.MBNCSUtil.CheckRevision.DoCheckRevision(valueStringFormula, new string[] { FileWar3EXE, FileStormDLL, FileGameDLL }, BNSharp.MBNCSUtil.CheckRevision.ExtractMPQNumber(mpqFileName));
                m_EXEVersionHash = Util.UTIL_CreateByteArray(EXEVersionHash, false);
                m_KeyInfoROC = CreateKeyInfo(keyROC, Util.UTIL_ByteArrayToUInt32(clientToken, false), Util.UTIL_ByteArrayToUInt32(serverToken, false));
                m_KeyInfoTFT = CreateKeyInfo(keyTFT, Util.UTIL_ByteArrayToUInt32(clientToken, false), Util.UTIL_ByteArrayToUInt32(serverToken, false));

                if (m_KeyInfoROC.Count == 36 && (!TFT || m_KeyInfoTFT.Count == 36))
                    return true;
                else
                {
                    if (m_KeyInfoROC.Count != 36)
                        Console.WriteLine("[BNCSUI] unable to create ROC key info - invalid ROC key");

                    if (TFT && m_KeyInfoTFT.Count != 36)
                        Console.WriteLine("[BNCSUI] unable to create TFT key info - invalid TFT key");
                }
            }
            else
            {
                if (!ExistsWar3EXE)
                    Console.WriteLine("[BNCSUI] unable to open [" + FileWar3EXE + "]");

                if (!ExistsStormDLL)
                    Console.WriteLine("[BNCSUI] unable to open [" + FileStormDLL + "]");

                if (!ExistsGameDLL)
                    Console.WriteLine("[BNCSUI] unable to open [" + FileGameDLL + "]");
            }

            return false;
        }
        public bool HELP_SID_AUTH_ACCOUNTLOGON()
        {
            // set m_ClientKey

            Byte[] buf = new Byte[32 + UserName.Length + 1];
            // nls_get_A( (nls_t *)m_nls, buf );

            m_NLS.LoginAccount(buf, 0, 32 + UserName.Length + 1);
            m_ClientKey = Util.UTIL_CreateByteArray(buf, 32 + UserName.Length + 1);
            return true;
        }
        public bool HELP_SID_AUTH_ACCOUNTLOGONPROOF(List<Byte> salt, List<Byte> serverKey)
        {
            // set m_M1

            Byte[] buf = new Byte[20];
            // nls_get_M1( (nls_t *)m_nls, buf, string( serverKey.begin( ), serverKey.end( ) ).c_str( ), string( salt.begin( ), salt.end( ) ).c_str( ) );
            m_NLS.LoginProof(buf, 0, 20, salt.ToArray(), serverKey.ToArray());
            m_M1 = Util.UTIL_CreateByteArray(buf, 20);
            return true;
        }
        public bool HELP_PvPGNPasswordHash(string userPassword)
        {
            // set m_PvPGNPasswordHash

            Byte[] buf = new Byte[20];
            buf = BNSharp.MBNCSUtil.OldAuth.HashPassword(userPassword);
            m_PvPGNPasswordHash = Util.UTIL_CreateByteArray(buf, 20);
            return true;
        }

        List<Byte> CreateKeyInfo(string key, UInt32 clientToken, UInt32 serverToken)
        {
            Byte[] Zeros = { 0, 0, 0, 0 };
            List<Byte> KeyInfo = new List<byte>();
            BNSharp.MBNCSUtil.CdKey Decoder = BNSharp.MBNCSUtil.CdKey.CreateDecoder(key);

            if (Decoder.IsValid)
            {
                Util.UTIL_AppendByteArray(KeyInfo, Util.UTIL_CreateByteArray((UInt32)key.Length, false));
                Util.UTIL_AppendByteArray(KeyInfo, Util.UTIL_CreateByteArray((uint)Decoder.Product, false));
                Util.UTIL_AppendByteArray(KeyInfo, Util.UTIL_CreateByteArray((uint)Decoder.Value1, false));
                Util.UTIL_AppendByteArray(KeyInfo, Util.UTIL_CreateByteArray(Zeros, 4));
                Byte[] buf = Decoder.GetHash(clientToken, serverToken);
                int Length = buf.Length;
                Util.UTIL_AppendByteArray(KeyInfo, Util.UTIL_CreateByteArray(buf, Length));

            }

            return KeyInfo;
        }
    }
}
